﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using snat.proxy.items.exceptions;
using snat.proxy;
using proxy.items;

namespace snat.proxy.items {
    public class Message : InstantiableItem, IComparable {

        private int id;
        public int ID {
            get {
                return id;
            }
        }

        object idonNetworkLock = new object();
        private string idonNetwork;
        public string IDonNetwork {
            get {
                lock (idonNetworkLock) {
                    if (idonNetwork == null) {
                        DataSet set = DataProxy.Instance.RunQuery(
                             @"SELECT IDonNetwork FROM MessageProperties
                             WHERE MessageID = " + ID);
                        try {
                            idonNetwork = set.Tables["Table"].Rows[0].Field<string>("IDonNetwork");
                        } catch (IndexOutOfRangeException) {
                           
                            throw new NoResultFromSQLException(@"SELECT IDonNetwork FROM MessageProperties
                                                            WHERE MessageID = " + ID);
                        }
                    }
                }
                return idonNetwork;
            }
        }

        object senderLock = new object();
        private Entity sender;
        public Entity Sender {
            get {
                lock (senderLock) {
                    if (sender == null) {
                        DataSet set = DataProxy.Instance.RunQuery(
                             @"SELECT EntityID FROM MessageSend
                             WHERE MessageID = " + ID);
                        try {
                            sender = new Entity(set.Tables["Table"].Rows[0]);
                        } catch (IndexOutOfRangeException) {
                            
                            throw new NoResultFromSQLException(@"SELECT EntityID FROM MessageSend
                                                            WHERE MessageID = " + ID);
                        }
                    }
                }
                return sender;
            }
        }

        private List<Entity> recipients;
        public List<Entity> Recipients {
            get {
                lock (senderLock) {
                    if (recipients == null){
                        //todo think about making this a Lazy<ListProxy>
                        recipients = new ListProxy<Entity>(@"SELECT EntityID FROM MessageReceive
                                                            WHERE MessageID = " + ID).ToList<Entity>();
                    }
                }
                return recipients;
            }
        }

        object restrictedLock = new object();
        private bool? restricted;
        public bool Restricted {
            get {
                lock (restrictedLock) {
                    if (restricted == null) {
                        DataSet set = DataProxy.Instance.RunQuery(
                             @"SELECT Restricted FROM MessageProperties
                             WHERE MessageID = " + ID);
                        try {
                            restricted = set.Tables["Table"].Rows[0].Field<bool>("Restricted");
                        } catch (IndexOutOfRangeException) {
                       
                            throw new NoResultFromSQLException(@"SELECT Restricted FROM MessageProperties
                                                            WHERE MessageID = " + ID);
                        }
                    }
                }
                return (bool)restricted;
            }
        }

        object dataLock = new object();
        private string data;
        public string Data {
            get {
                lock (dataLock) {
                    if (data == null) {
                        DataSet set = DataProxy.Instance.RunQuery(
                             @"SELECT Data FROM MessageProperties
                             WHERE MessageID = " + ID);
                        try {
                            idonNetwork = set.Tables["Table"].Rows[0].Field<string>("Data");
                        } catch (IndexOutOfRangeException) {
                        
                            throw new NoResultFromSQLException(@"SELECT Data FROM MessageProperties
                                                            WHERE MessageID = " + ID);
                        }
                    }
                }
                return data;
            }
        }

        object timeStampLock = new object();
        private DateTime? timeStamp;
        public DateTime TimeStamp {
            get {
                lock (timeStampLock) {
                    if (timeStamp == null) {
                        DataSet set = DataProxy.Instance.RunQuery(
                                 @"SELECT TimeStamp FROM MessageProperties
                             WHERE MessageID = " + ID);
                        try {
                            timeStamp = set.Tables["Table"].Rows[0].Field<DateTime>("TimeStamp");
                        } catch (IndexOutOfRangeException) {
                      
                            throw new NoResultFromSQLException(@"SELECT TimeStamp FROM MessageProperties
                                                            WHERE MessageID = " + ID);
                        }
                    }
                }
                return (DateTime)timeStamp;
            }
        }

        //todo make instantiate better for greedy stuff, complex queries for this one
        //todo remove all the greedy crap
        public Message(DataRow _row, bool _isGreedy = true)
            : this(_row.Field<int>("MessageID")) {
            this.idonNetwork = _row.Field<string>("IDOnNetwork");
            this.restricted = _row.Field<bool>("Restricted");
            this.data = _row.Field<string>("Data");
            this.timeStamp = _row.Field<DateTime>("TimeStamp");
            this.sender = new Entity(_row.Field<int>("EntityID"), _row.Field<string>("EntityName"));

            if (_isGreedy) {
                //todo sort out this query
                this.recipients = new ListProxy<Entity>(@"SELECT EntityID, EntityName
                                                          FROM MessageReceive NATURAL JOIN Entity
                                                          WHERE MessageReceive.MessageID = " + ID, _isGreedy).ToList<Entity>();
            }
        }


        //todo remove isgreedy. placeholder.
        public Message(DataRow _row, bool _isGreedy, List<Entity> _recipients) : this(_row, false){

            
        
        }

        public Message(int _id, Entity _sender = null, List<Entity> _recipients = null, 
                        string _idonNetwork = null, bool? _restricted = null, 
                        DateTime? _timeStamp = null, string _data = null) {
            this.id = _id;
            this.sender = _sender;
            this.recipients = _recipients;
            this.idonNetwork = _idonNetwork;
            this.restricted = _restricted;
            this.data = _data;
            this.timeStamp = _timeStamp;
        }

        public void Instantiate() {
            string dummy1 = IDonNetwork;
            string dummy2 = Data;
            bool dummy3 = Restricted;
            Entity dummy4 = Sender;
            List<Entity> dummy5 = Recipients;
        }

        public int CompareTo(object obj) {
            return TimeStamp.CompareTo((obj as Message).TimeStamp);
        }

        public override string ToString() {
            return ID.ToString();
        }

        public override void Instantiate(DataSet data) {
            if(recipients != null){
                //todo todo
                Console.WriteLine("Throw a fit!!!");
                //not allowed, can't change recipients
                //need a new error class to be thrown here
            }
            
            var allRecipients = data.Tables["Recipients"].AsEnumerable();

            var myRecipients = from r in allRecipients
                               where r.Field<int>("MessageID") == id
                               select r.Field<int>("RecipientID");

            

            //new Entity(



        }
    }
}
